当前位置: 首页 > 知识库问答 >
问题:

如何创建MP3从文本与谷歌TTS?

汪才英
2023-03-14

如何创建MP3从任何文本与谷歌TTS?

1) 我试图找到谷歌。翻译API,但只找到“音频到文本”,除了“文本到音频”!

2) 我试着把语音合成转换成mp3,但还是一无所获!

3) 我发现只有一个网站“beta.soundoftext.com”,它们生成的mp3音频文件没有API接口。

所以,有人能帮我吗?我正在为我的网站(专用服务器)寻找任何将文本转换为语音的方法。谢谢!

共有3个答案

宗沛
2023-03-14

Guy Rotem编写了一个js函数来获取tk令牌。我将其改编为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,因为这是谷歌的回报。然后可以使用其他一些库来转换。mpga。mp3

彭阳朔
2023-03-14

已经为它创建了一个Python脚本,该脚本现在可以在Github上使用。

这里的所有输入都非常简单,除了语言部分,有些语言代码可能不太为用户所熟悉,在这种情况下,谷歌的留档是可用的,您可以检查您希望引擎使用的语言的代码是什么。

督阿苏
2023-03-14

我是文本之声的创造者。

我的网站确实有一个应用编程接口!(截至上周)

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

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

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

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

 类似资料:
  • 我能够使用链接中包含的教程转录音频(https://cloud.google.com/speech-to-text/docs/async-recognize),但它仅适用于WAV格式的音频。我想让它与MP3或M4A格式的音频一起工作。 我已经测试了链接中包含的所有可能性(https://github.com/GoogleCloudPlatform/java-docs-samples/blob/ma

  • 问题内容: 我有一个包含数千行的生成的文件,如下所示: 有些行的字段更多,而其他行的字段较少,但是所有行都遵循相同的键值对模式,每行都有一个TSN字段。 在对文件进行一些分析时,我编写了如下所示的循环,以将文件读入字典: …这很好,并且确实满足我的要求(这只是一个简单的示例)。 但是,对于我和以下内容而言,它并不是特别“ pythonic”: 哪个感觉“笨拙”(在字段上迭代了多少次?)。 仅使用标

  • 我正在遵循官方的Google身份验证流程。我的应用程序已经使用了最新版本的Google地图。 项目 应用程序 地图下方有一条红线,弹出窗口显示找到了11.8.0和11.4.2。构建错误消息如下:, 错误:任务“:应用程序:进程”的执行失败。 请通过更新谷歌服务插件的版本来修复版本冲突(有关最新版本的信息,请访问https://bintray.com/android/android-tools/co

  • 我使用的JSON API-Google API客户端库Java访问对象在谷歌云存储。我需要在桶中创建(而不是上传)一个空文件夹。谷歌开发人员网络控制台有创建目录的选项,但是JavaAPI和gsutil命令都没有创建文件夹命令。如果有人知道如何这样做,请告诉我。提前感谢...

  • 我有一个应用引擎项目。 我也有谷歌云功能。 我想从App Engine项目中调用谷歌云功能。我就是没法让它发挥作用。 是的,如果我将函数完全公开(即将云函数设置为“允许所有流量”,并为“所有用户”创建一个允许调用函数的规则),它就可以工作。但是如果我限制这两个设置中的任何一个,它会立即停止工作,我得到403。 应用程序和函数在同一个项目中,所以我至少假设将函数设置为“仅允许内部流量”应该可以正常工