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

时间:2017-11-03 16:12:25

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

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

1)我尝试找到google.translate API,但只查找“audio to text”,“text to audio”除外!

2)我试着找到SpeechSynthesis转换为mp3,但又找不到任何东西!

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

所以,请有人帮助我。 我搜索任何方法将文本转换为SPEECH为我的网站(专用服务器)。谢谢!

3 个答案:

答案 0 :(得分:2)

我是“声音之声”的创作者。

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

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

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

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

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

答案 1 :(得分:0)

A Python script have been created for it,该脚本现已在Github上提供。

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

答案 2 :(得分:0)

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