接入人声克隆基础版Web SDK

智能生产制作提供人声克隆基础版Web SDK接入能力,您可以根据需求在前端页面文件中集成人声克隆服务。通过阅读本文,您可以了解如何接入人声克隆基础版Web SDK。

使用说明

本文将指导您集成版本号为0.0.2的人声克隆基础版Web SDK,接入界面如下:

image.png

操作步骤

  1. 在项目前端页面文件中的<head>标签处引入人声克隆Web SDK。

    <head>
       <script src="https://g.alicdn.com/video-cloud-fe/tts-factory/0.0.2/index.js"></script>
    </head>

    在<body>标签处添加一个用以挂载页面的<div>节点。

    <body>
      <div id="app" ></div> // 您可以根据需要改变 container 高度
    </body>
  2. 初始化Web SDK。

    展开查看示例代码

      const ttsFactory = window.AliyunTTSFactory.init({
          container: container,
          api: {
            createVoiceId: async (params) => {
              const res = await request('CreateCustomizedVoiceJob', {
                VoiceName: params.voiceName,
                VoiceId: params.voiceId,
                Gender: params.gender,
                Scenario: params.scenario,
              });
    
              return {
                success: get(res, 'data.Success', false),
                data: {
                  voiceId: get(res, 'data.Data.VoiceId', ''),
                },
              };
            },
            getRecorderList: async (params) => {
              const res = await requestGet('GetDemonstrationForCustomizedVoiceJob', {
                Scenario: params.scenario,
              });
    
              return {
                success: get(res, 'data.Success', false),
                data: get(res, 'data.Data.DemonstrationList', []).map((item) => {
                  return {
                    audioId: item.AudioId,
                    audioUrl: item.DemoAudio,
                    text: item.Text,
                  };
                }),
              };
            },
            uploadRecord: async (params) => {
              const fileName = `${params.voiceId}-${
                    params.index
                  }-${Date.now()}.wav`;
              const result = await uploadFile(fileName,params.file);
              console.log('uploadRecord', params,fileName,result);
              return { success: true, data: { fileUrl: result.url } }
            },
            validRecord: async (params) => {
              const res = await request('DetectAudioForCustomizedVoiceJob', {
                VoiceId: params.voiceId,
                RecordUrl: params.uploadData.fileUrl,
                AudioRecordId: params.index + 1,
              });
    
              return {
                success:  get(res, 'data.Success', false),
                  data: {
                    pass:  get(res, 'data.Data.Pass', false),
                    reason: get(res, 'data.Data.Reason', ''),
                  },
              };
            },
            submitRecord: async (params) => {
              const res = await request('SubmitCustomizedVoiceJob', {
                VoiceId: params.voiceId,
                // DemoAudioMediaURL: '', 人声克隆输出demo音频的地址
              });
              return {
                success: get(res, 'data.Success', false),
              };
            },
            getCopywriting:  (config)=>{
              // 文案修改示例
              console.log('>>config', config);
              config.views.Tutorial.startBtn = '开始'
              return config;
            }
          },
        });
    • 初始化InitConfig实例:

      interface InitConfig {
        container: HTMLElement;
        api: {
          // 创建voieId
          createVoiceId: (params: { voiceId?: string, voiceName: string, gender: string, scenario: string }) => Promise<Result<{ voiceId: string }>>;
          // 获取录制列表
          getRecorderList: (params: { sex: string, scenario: string }) => Promise<Result>;
          // 上传录制音频
          uploadRecord: (params: any) => Promise<Result<{fileUrl: string}>>;
          // 验证录制音频
          validRecord: (params: any) => Promise<Result<{ reason: string; pass: boolean }>>;
          // 提交录制音频
          submitRecord: (params: any) => Promise<Result>;
          // 文案修改
          getCopywriting?:(config: any)=>T;
        }
      }
    • AliyunTTSFactory实例:

      class AliyunTTSFactory {
        destroy(): void
      }
  3. 释放实例。使用destroy方法可以释放实例,释放后容器为空元素。

    ttsFactory.destroy();

示例代码

展开查看示例代码

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8" />
  <link rel="icon" type="image/svg+xml" href="/vite.svg" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.21/lodash.min.js"></script>
  <script src="http://gosspublic.alicdn.com/aliyun-oss-sdk-6.19.0.min.js"></script>
  <script src="https://g.alicdn.com/video-cloud-fe/tts-factory/0.0.2/index.js"></script>

  <title>ALI TTS DEMO</title>
</head>

<body>
  <div id="app"></div>
  <script>
    async function request(action, params) {
      const res = await fetch('/openApiPost', {
        method: 'POST', body: JSON.stringify({...params, Action: action}), headers: {
          'Content-Type': 'application/json; charset=utf-8'
        }
      })
      const data = await res.json();
      return {data};
    }

    async function requestGet(action, params) {
      const searchParams = new URLSearchParams();
      searchParams.set('Action', action);
      Object.keys(params).forEach((key) => {
        searchParams.set(key, params[key]);
      });
      const res = await fetch(`/openApi?${ searchParams.toString() }`, {method: 'GET'})
      const data = await res.json();
      return {data};
    }

    const refreshSts = async () => {
      // 创建上传到oss的sts,参考文档 https://help.aliyun.com/zh/oss/developer-reference/authorize-access-6?spm=a2c4g.11186623.0.i6#section-iy3-bfe-7mn
      const res = await fetch("/createSTS", {method: 'POST'});
      const data = await res.json();
      return data.data;
    }

    const uploadFile = async (fileName,file) => {
      // 上传oss 参考文档 https://help.aliyun.com/zh/oss/developer-reference/simple-upload-8?spm=a2c4g.11186623.0.0.27d22dc50M8glG
      const sts = await refreshSts();
      const client = new OSS({
        // yourRegion填写Bucket所在地域。以华东1(杭州)为例,yourRegion填写为oss-cn-hangzhou。
        region: `oss-${ sts.region }`,
        accessKeyId: sts.accessKeyId,
        accessKeySecret: sts.accessKeySecret,
        stsToken: sts.securityToken,
        // 填写Bucket名称。
        bucket: sts.bucket,
        // 刷新临时访问凭证。
        refreshSTSToken: async () => {
          const refreshToken = await refreshSts();
          return {
            accessKeyId: refreshToken.accessKeyId,
            accessKeySecret: refreshToken.accessKeySecret,
            stsToken: refreshToken.securityToken,
          };
        },
      });

      const result = await client.multipartUpload(fileName, file, {
        progress: (p, _cpt, res) => {
          console.log('res', res);
        },
        parallel: 2,
        partsize: 1024 * 512,
      });

      const url = new URL(result.res.requestUrls[0]);
      return {url: `${ url.origin }${ url.pathname }`}

    }

    const get = _.get;
    const container = document.getElementById('app');
    const ttsFactory = window.AliyunTTSFactory.init({
      container: container,
      api: {
        createVoiceId: async (params) => {
          const res = await request('CreateCustomizedVoiceJob', {
            VoiceName: params.voiceName,
            VoiceId: params.voiceId,
            Gender: params.gender,
            Scenario: params.scenario,
          });

          return {
            success: get(res, 'data.Success', false),
            data: {
              voiceId: get(res, 'data.Data.VoiceId', ''),
            },
          };
        },
        getRecorderList: async (params) => {
          const res = await requestGet('GetDemonstrationForCustomizedVoiceJob', {
            Scenario: params.scenario,
          });

          return {
            success: get(res, 'data.Success', false),
            data: get(res, 'data.Data.DemonstrationList', []).map((item) => {
              return {
                audioId: item.AudioId,
                audioUrl: item.DemoAudio,
                text: item.Text,
              };
            }),
          };
        },
        uploadRecord: async (params) => {
          const fileName = `${params.voiceId}-${
                params.index
              }-${Date.now()}.wav`;
          const result = await uploadFile(fileName,params.file);
          console.log('uploadRecord', params,fileName,result);
          return { success: true, data: { fileUrl: result.url } }
        },
        validRecord: async (params) => {
          const res = await request('DetectAudioForCustomizedVoiceJob', {
            VoiceId: params.voiceId,
            RecordUrl: params.uploadData.fileUrl,
            AudioRecordId: params.index + 1,
          });

          return {
            success:  get(res, 'data.Success', false),
              data: {
                pass:  get(res, 'data.Data.Pass', false),
                reason: get(res, 'data.Data.Reason', ''),
              },
          };
        },
        submitRecord: async (params) => {
          const res = await request('SubmitCustomizedVoiceJob', {
            VoiceId: params.voiceId,
            // DemoAudioMediaURL: '', 人声克隆输出demo音频的地址
          });
          return {
            success: get(res, 'data.Success', false),
          };
        },
        getCopywriting:  (config)=>{
          // 文案修改示例
          console.log('>>config', config);
          config.views.Tutorial.startBtn = '开始克隆'
          return config;
        }
      },
    });
  </script>
</body>

</html>

相关文档

了解更多关于人声克隆的详情,请参见人声克隆