【问题标题】:How to create mp3 from text with Google TTS?如何使用 Google TTS 从文本创建 mp3?
【发布时间】:2020-01-31 10:57:51
【问题描述】:

如何使用 Google TTS 从任何文本创建 mp3?

1) 我尝试查找 google.translate API,但只找到“音频到文本”,“文本到音频”除外!

2) 我试图找到 SpeechSynthesis 转换为 mp3,但又一无所获!

3) 我只找到“beta.soundoftext.com”网站,他们生成没有 API 接口的 mp3 音频文件。

那么,谁能帮帮我,拜托。 我正在为我的网站(专用服务器)寻找将文本转换为语音的任何方法。谢谢!

【问题讨论】:

  • 对于 (1) 尝试研究:"text to speech" API 而不是 “文本到音频”。在此处告诉我们您使用 Google TTS(显示代码)具体尝试过什么以及您收到的错误消息...

标签: audio web mp3 text-to-speech google-text-to-speech


【解决方案1】:

我是文字之声的创造者。

我的网站确实有一个 API! (截至上周)

您可以在此处找到 API 的文档:https://soundoftext.com/docs

但是,在幕后,我只是使用了一个自动为我生成 Google 翻译 TTS 链接的 npm 库。具体来说,我正在使用这个库:https://www.npmjs.com/package/google-tts-api

我很确定每一种流行语言都有一个做类似事情的库,如果你告诉我你喜欢使用哪种语言,我可以帮助你找到它。

或者你可以使用我的 API =)

【讨论】:

    【解决方案2】:

    A Python script have been created for it 并且该脚本现在可以在 Github 上使用。

    那里的所有输入都非常简单,除了用户可能不太熟悉某些语言代码的语言部分,在这些情况下documentation from Google is available,您可以检查您希望引擎使用的语言的代码是什么.

    【讨论】:

      【解决方案3】:

      Guy Rotem 编写了一个 js 函数来获取 tk 令牌 here。我为 Java 改编了它:

      public class Hasher {
          public long shiftLeftOrRightThenSumOrXor(long num, String[] opArray) {
              long result = num;
      
              int current = 0;
              while (current < opArray.length)  {
                  char op1 = opArray[current].charAt(1);  //  '+' | '-' ~ SUM | XOR
                  char op2 = opArray[current].charAt(0);  //  '+' | '^' ~ SLL | SRL
                  char xd = opArray[current].charAt(2);   //  [0-9a-f]
      
                  assertError(op1 == '+'
                          || op1 == '-', "Invalid OP: " + op1);
                  assertError(op2 == '+'
                          || op2 == '^', "Invalid OP: " + op2);
                  assertError(('0' <= xd && xd <= '9')
                          || ('a' <= xd && xd <='f'), "Not an 0x? value: " + xd);
      
                  int shiftAmount = hexCharAsNumber(xd);
                  int mask = (op1 == '+') ? ((int) result) >>> shiftAmount : ((int) result) << shiftAmount;
      
                  long subresult = (op2 == '+') ? (((int) result) + ((int) mask) & 0xffffffff)
                          : (((int) result) ^ mask);
                  result = subresult;
                  current++;
              }
      
              return result;
          }
      
          public void assertError(boolean cond, String e) {
              if (!cond) {
                  System.err.println();
              }
          }
      
          public int hexCharAsNumber(char xd) {
              return (xd >= 'a') ? xd - 87 : Character.getNumericValue(xd);
          }
      
          public int[] transformQuery(String query) {
              int[] e = new int[1000];
              int resultSize = 1000;
      
              for (int f = 0, g = 0; g < query.length(); g++) {
                  int l = query.charAt(g);
                  if (l < 128) {
                      e[f++] = l;                 //  0{l[6-0]}
                  } else if (l < 2048) {
                      e[f++] = l >> 6 | 0xC0;     //  110{l[10-6]}
                      e[f++] = l & 0x3F | 0x80;   //  10{l[5-0]}
                  } else if (0xD800 == (l & 0xFC00) &&
                          g + 1 < query.length() && 0xDC00 == (query.charAt(g + 1) & 0xFC00)) {
                      //  that's pretty rare... (avoid ovf?)
                      l = (1 << 16) + ((l & 0x03FF) << 10) + (query.charAt(++g) & 0x03FF);
                      e[f++] = l >> 18 | 0xF0;        //  111100{l[9-8*]}
                      e[f++] = l >> 12 & 0x3F | 0x80; //  10{l[7*-2]}
                      e[f++] = l & 0x3F | 0x80;       //  10{(l+1)[5-0]}
                  } else {
                      e[f++] = l >> 12 | 0xE0;        //  1110{l[15-12]}
                      e[f++] = l >> 6 & 0x3F | 0x80;  //  10{l[11-6]}
                      e[f++] = l & 0x3F | 0x80;       //  10{l[5-0]}
                  }
      
                  resultSize = f;
              }
      
              return Arrays.copyOf(e, resultSize);
          }
      
          public long normalizeHash(long encondindRound2) {
              if (encondindRound2 < 0) {
                  encondindRound2 = (encondindRound2 & 0x7fffffff) + 0x80000000L;
              }
              return (encondindRound2) % 1_000_000;
          }
      
          /*
          /   EXAMPLE:
          /
          /   INPUT: query: 'hola', windowTkk: '409837.2120040981'
          /   OUTPUT: '70528.480109'
          /
          */
          public String calcHash(String query, String windowTkk) {
              //  STEP 1: spread the the query char codes on a byte-array, 1-3 bytes per char
              int[] bytesArray = transformQuery(query);
      
              //  STEP 2: starting with TKK index,
              // add the array from last step one-by-one, and do 2 rounds of shift+add/xor
              String[] d = windowTkk.split("\\.");
              int tkkIndex = 0;
              try  {
                  tkkIndex = Integer.valueOf(d[0]);
              }
              catch (Exception e)  {
                  e.printStackTrace();
              }
      
              long tkkKey = 0;
              try  {
                  tkkKey = Long.valueOf(d[1]);
              }
              catch (Exception e)  {
                  e.printStackTrace();
              }
      
              int current = 0;
              long result = tkkIndex;
              while (current < bytesArray.length)  {
                  result += bytesArray[current];
                  long subresult = shiftLeftOrRightThenSumOrXor(result,
                          new String[] {"+-a", "^+6"});
                  result = subresult;
                  current++;
              }
              long encondingRound1 = result;
              //System.out.println("encodingRound1: " + encondingRound1);
      
              //  STEP 3: apply 3 rounds of shift+add/xor and XOR with they TKK key
              long encondingRound2 = ((int) shiftLeftOrRightThenSumOrXor(encondingRound1,
                      new String[] {"+-3", "^+b", "+-f"})) ^ ((int) tkkKey);
              //System.out.println("encodingRound2: " + encondingRound2);
      
              //  STEP 4: Normalize to 2s complement & format
              long normalizedResult = normalizeHash(encondingRound2);
              //System.out.println("normalizedResult: " +  normalizedResult);
      
              return String.valueOf(normalizedResult) + "."
                      + (((int) normalizedResult) ^ (tkkIndex));
          }
      }
      

      一旦你有了tk,你只需要像这样发送一个HTTP请求(使用okhttp库发送请求):

      HttpUrl.Builder urlBuilder = HttpUrl.parse("https://translate.google.com/translate_tts").newBuilder();
      urlBuilder.addQueryParameter("ie", "UTF-8");
      urlBuilder.addQueryParameter("q", foreignWord);
      urlBuilder.addQueryParameter("tl", "de");
      urlBuilder.addQueryParameter("total", "1");
      urlBuilder.addQueryParameter("idx", "0");
      urlBuilder.addQueryParameter("textlen",
              String.valueOf(foreignWord.length()));
      urlBuilder.addQueryParameter("tk", hasher.getTk(foreignWord));
      urlBuilder.addQueryParameter("client", "webapp");
      urlBuilder.addQueryParameter("prev", "input");
      
      String url = urlBuilder.build().toString();
      Request request = new Request.Builder()
              .url(url)
              .addHeader("User-Agent", "Mozilla/5.0...")
              .addHeader("Accept-Language", Locale.US.getLanguage())
              .addHeader("Referer", "https://translate.google.com/")
              .get()
              .build();
      
      OkHttpClient client = new OkHttpClient();
      Call call = client.newCall(request);
      Response response = call.execute();
      InputStream inputStream = response.body().byteStream();
      FileOutputStream fileOutputStream = new FileOutputStream(path + "/audio/" + foreignWord + ".mpga");
      byte dataBuffer[] = new byte[1024];
      int bytesRead;
      while ((bytesRead = inputStream.read(dataBuffer, 0, 1024)) != -1) {
          fileOutputStream.write(dataBuffer, 0, bytesRead);
      }
      

      它将文件保存为.mpga,因为这是 google 返回的内容。然后,您可以使用其他一些库将.mpga 转换为.mp3

      【讨论】:

        猜你喜欢
        • 2011-03-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-10-09
        • 2012-04-20
        • 1970-01-01
        • 1970-01-01
        • 2019-02-05
        相关资源
        最近更新 更多