Delphi专题 ·

Delphi使用百度语音合成服务

简介

百度语音合成服务,基于HTTP请求的REST API接口,将文本转换为可以播放的音频文件。
合成的文件格式为 mp3,pcm(8k及16k),wav(16k),具体见aue参数

  • 多音字可以通过标注自行定义发音。格式如:重(chong2)报集团。
  • 目前只有中英文混合这一种语言,优先中文发音。示例: " I bought 3 books” 发音 “three”; “ 3 books are bought” 发音 “三”; “我们买了 3 books” 发音“三”

文档地址:http://ai.baidu.com/docs#/TTS-API/top

调用流程

创建应用

  • 1、登录百度云服务平台,没有账号请先自行注册https://cloud.baidu.com/
  • 2、在产品服务——人工智能——百度语音 下创建一个应用,输入应用名称和应用描述,点击创建应用。创建成功后点击查看应用详情。会生成API Key和Secret Key

获取token

function Getaccess_token(grant_type,client_id,client_secret:string):string;  //获取token
var
 idhttp2:Tidhttp;
 authHost:string;
 tokSl:Tstringlist;
begin
  authHost:= 'http://aip.baidubce.com/oauth/2.0/token';
  try
    tokSl:=Tstringlist.Create;
    idhttp2:=Tidhttp.Create(nil);
    toksl.Add('grant_type=' + grant_type);
    toksl.Add('client_id=' + client_id);
    toksl.Add('client_secret=' + client_secret);
    Result:=idhttp2.Post(authHost,toksl);
  finally
    toksl.Free;
    idhttp2.DisposeOf;
  end;
end;

可得到如下结果

{
    "access_token": "1.a6b7dbd428f731035f771b8d********.86400.1292922000-2346678-124328",
    "expires_in": 2592000,
    "refresh_token": "2.385d55f8615fdfd9edb7c4b********.604800.1293440400-2346678-124328",
    "scope": "public audio_tts_post ...",
    "session_key": "ANXxSNjwQDugf8615Onqeik********CdlLxn",
    "session_secret": "248APxvxjCZ0VEC********aK4oZExMB",
}

scope中含有audio_tts_post 表示有语音合成能力,没有该audio_tts_post 的token调用接口会返回502错误。 在结果中可以看见 token = 1.a6b7dbd428f731035f771b8d********.86400.1292922000-2346678-124328,在2592000秒(30天)后过期
响应数据包如下所示,其中 “access_token” 字段即为请求 REST API 所需的令牌, 默认情况下,Access Token 有效期为30天,开发者需要对 Access Token的有效性进行判断,如果Access Token过期可以重新获取。

请求方式及参数基本说明

语音合成接口支持 POST 和 GET两种方式, 推荐POST方式请求。 正式地址:http://tsn.baidu.com/text2audio 或 https://tsn.baidu.com/text2audio

  • 1、POST 方式(推荐), 文本小于2048个中文字或者英文数字。
  • 2、GET 方式,拼接后的url总长度不多于1000个字符,不推荐长文本合成使用。

请求方式和参数

参数 可需 描述
tex 必填 合成的文本,使用UTF-8编码。小于2048个中文字或者英文数字。(文本在百度服务器内转换为GBK后,长度必须小于4096字节)
tok 必填 开放平台获取到的开发者access_token(见上面的“鉴权认证机制”段落)
cuid 必填 用户唯一标识,用来计算UV值。建议填写能区分用户的机器 MAC 地址或 IMEI 码,长度为60字符以内
ctp 必填 客户端类型选择,web端填写固定值1
lan 必填 固定值zh。语言选择,目前只有中英文混合模式,填写固定值zh
spd 选填 语速,取值0-15,默认为5中语速
pit 选填 音调,取值0-15,默认为5中语调
vol 选填 音量,取值0-15,默认为5中音量
per 选填 发音人选择, 0为普通女声,1为普通男生,3为情感合成-度逍遥,4为情感合成-度丫丫,默认为普通女声
aue 选填 3为mp3格式(默认); 4为pcm-16k;5为pcm-8k;6为wav(内容同pcm-16k); 注意aue=4或者6是语音识别要求的格式,但是音频内容不是语音识别要求的自然人发音,所以识别效果会受影响。
function GetMidString(s: string; d: string; c: string): string; // 取字符串中间
var
  i, n: Integer;
begin
  try
    i := pos(d, s);
    n := pos(c, copy(s, i + 1, Length(s) - i));
    Result := copy(s, i + Length(d), n - Length(d));
  except
    Result := '';
  end;
end;

function NBGetAdapterAddress(ID: integer): String; //用于得到一个cuid用户唯一标识
Var
  NC: TNCB;
  ADAPTE: TADAPTERSTATUS;
  LANAENU: TLANAENUM;
  intId: integer;
  cR: AnsiChar;
  strTem: String;
Begin
  Result := '';
  Try
    ZeroMemory(@NC, SizeOf(NC));
    NC.ncb_command := Chr(NCBENUM);
    cR := NetBios(@NC);
    // Reissue enum command
    NC.ncb_buffer := @LANAENU;
    NC.ncb_length := SizeOf(LANAENU);
    cR := NetBios(@NC);
    If Ord(cR) <> 0 Then
      exit;
    ZeroMemory(@NC, SizeOf(NC));
    NC.ncb_command := Chr(NCBRESET);
    NC.ncb_lana_num := LANAENU.lana[ID];
    cR := NetBios(@NC);
    If Ord(cR) <> 0 Then
      exit;
    ZeroMemory(@NC, SizeOf(NC));
    NC.ncb_command := Chr(NCBASTAT);
    NC.ncb_lana_num := LANAENU.lana[ID];
    StrPCopy(NC.ncb_callname, '*');
    NC.ncb_buffer := @ADAPTE;
    NC.ncb_length := SizeOf(ADAPTE);
    cR := NetBios(@NC);
    strTem := '';
    For intId := 0 To 5 Do
      strTem := strTem + InttoHex(integer(ADAPTE.adapter_address[intId]), 2);
    Result := strTem;
  except
    Result := 'Error';
  End;
end;

procedure TForm2.Button1Click(Sender: TObject);//具体调用
var
  str1, str3, str4: string;
  str2: string;
  res: Tmemorystream;
  authHost:string;
  tokSl:Tstringlist;
  tex, tok, cuid: string;
  spd, pit, vol, per: string;
  grant_type,client_id,client_secret:string;
begin
  if Memo1.Text = '' then
    showmessage('请先输入要转换的文字!')
  else if Edit1.Text = '' then
    showmessage('请先选择语音保存地址!')
  else
  begin
    if not internetcheckconnection('http://www.baidu.com', 1, 0) then
      showmessage('联网失败,请先检查网络连接!')
    else if Length(Memo1.Text) > 512 then
      showmessage('一次转换文字不要超过512个文字,否则可能出错!')
    else
    begin
      cuid := NBGetAdapterAddress(0);
      spd := ComboBox1.Text;
      pit := ComboBox2.Text;
      vol := ComboBox3.Text;
      per := inttostr(ComboBox4.ItemIndex);
      Filename := FormatDateTime('yyyy年mm月dd日 hh时nn分ss秒', now()) + '转换语音.mp3';
      grant_type:='client_credentials';//grant_type: 必须参数,固定为client_credentials

      client_id:='你的应用的API Key';//必须参数,应用的API Key

      client_secret:='你的应用的Secret Key';//必须参数,应用的Secret Key

      tok :=GetMidString(Getaccess_token(grant_type,client_id,client_secret),'access_token":"','",');  //如果直接使用,注意token会在30天后过期
      res := Tmemorystream.Create;
      IdHTTP1.Response.ContentType := 'Content-Type:audio/mp3';
      IdHTTP1.Request.ContentType := 'application/x-www-form-urlencoded';
      str := ('http://tsn.baidu.com/text2audio?tex=' + Memo1.Text +
        '&lan=zh&cuid=' + cuid + '&ctp=1&tok=' + tok + '&spd=' + spd + '&pit=' +
        pit + '&vol=' + vol + '&per=' + per);
      IdHTTP1.Get(Tiduri.UrlEncode(UTF8Encode(str)), res); //POST 方式(推荐), 文本小于2048个中文字或者英文数字。GET 方式,拼接后的url总长度不多于1000个字符,不推荐长文本合成使用。
      res.SaveToFile(Edit1.Text + Filename);
//如果不需要保存到本地,上边可以不用下载下来,下边的直接改成MediaPlayer1.Filename := Tiduri.UrlEncode(UTF8Encode(str)) + '.mp3';
      MediaPlayer1.DeviceType :=dtAutoSelect;
      if (MediaPlayer1.DeviceID <> 0) then
      begin
        if (MediaPlayer1.Mode = mpplaying) then
          MediaPlayer1.Stop;
      end;
      MediaPlayer1.Enabled := true;
      MediaPlayer1.Filename := Edit1.Text + Filename;
      MediaPlayer1.Open;
      MediaPlayer1.Play;
    end;
  end;
end;

源码下载

当前隐藏内容需要支付 0 积分

已有 0 人支付

461

参与评论