Как создать mp3 из текста с помощью Google TTS?

Как создать mp3 из любого текста с помощью Google TTS?

1) Я пытаюсь найти API google.translate, но нашел только «аудио в текст», кроме «текст в аудио»!

2) Пытаюсь найти преобразование SpeechSynthesis в mp3, но опять ничего не нахожу!

3) Я нашел только сайт "beta.soundoftext.com", они генерируют аудиофайл в формате mp3 без интерфейса API.

Итак, кто-нибудь может мне помочь, пожалуйста. Я ищу любые способы конвертировать текст в РЕЧЬ для своего веб-сайта (выделенного сервера). Спасибо!


person inpost    schedule 03.11.2017    source источник
comment
для (1) попробуйте исследовать: преобразование текста в речь API вместо преобразования текста в аудио. Сообщите нам здесь, что вы пробовали конкретно с помощью Google TTS (показать код) и какое сообщение об ошибке вы получили ...   -  person VC.One    schedule 07.11.2017


Ответы (3)


Я создатель Sound of Text.

У моего сайта есть API! (По состоянию на прошлую неделю)

Вы можете найти документацию по API здесь: https://soundoftext.com/docs.

Однако за кулисами я просто использую библиотеку npm, которая автоматически генерирует для меня ссылку Google Translate TTS. В частности, я использую эту библиотеку: https://www.npmjs.com/package/google-tts-api

Я почти уверен, что у каждого популярного языка есть библиотека, которая делает то же самое, и я могу помочь вам найти ее, если вы скажете мне, какой язык вы предпочитаете использовать.

Или вы можете просто использовать мой API =)

person ncpierson    schedule 13.11.2017

Сценарий Python был создан для него, и теперь сценарий доступен на Github.

Весь ввод здесь довольно прост, за исключением языковой части, где некоторый языковой код может быть менее знаком пользователям, в этих случаях доступна документация от Google, и вы можете проверить код для языка, на котором должен работать движок.

person user930067    schedule 13.11.2017

Гай Ротем написал функцию 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, потому что это то, что возвращает Google. Затем вы можете использовать некоторые другие библиотеки для преобразования .mpga в .mp3.

person parsecer    schedule 31.01.2020