Способ воспроизведения выходного формата Azure "audio-16khz-128kbitrate-mono-mp3" на Java - PullRequest
0 голосов
/ 10 октября 2019

Раньше я получал формат вывода "riff-24khz-16bit-mono-pcm" из службы API Azure Test-to-Speech. Из-за некоторых технических изменений, аудио тексты, которые мы сейчас получаем, находятся в аудио-16 кГц-128 кбитрат-моно-mp3.

Перед этим изменением мы использовали для воспроизведения аудио из аудиотекста следующее:

    String stepTitle=soundData; // audioText output from Azure
    byte[] bytes = stepTitle.getBytes();
    Base64.Decoder decoder = Base64.getDecoder();

    byte[] decoded = decoder.decode(bytes);

    InputStream input = new ByteArrayInputStream(decoded);
    AudioInputStream audioInput = null;
    try {
        ///////// This line is giving exception ////////////////////////
        audioInput = AudioSystem.getAudioInputStream(input);
    } catch (UnsupportedAudioFileException | IOException e) {
        e.printStackTrace();
    } 

    AudioFormat audioFormats = new AudioFormat(
            AudioFormat.Encoding.PCM_SIGNED,
            24000,
            16,
            1,
            1 * 2,
            24000,
            false);

Как упоминалось выше, при получении входного аудиопотока я получаю UnsupportedAudioFileException .

Я пробовал с mp3plugin.jar. Но я думаю, что я не смог заставить его работать правильно. Пожалуйста, помогите!

1 Ответ

0 голосов
/ 14 октября 2019

Обращаясь к официальной документации TTS REST API , я обменяюсь на токен с ключом и использую этот токен для преобразования текста в речь. Я получу байтовый массив аудиоданных, а затем использую JLayer для воспроизведения звука.

Вот мой пример:

public class TestTTS {

    static String key = "f1a0ea***********fa5e35";
    static String tokenEndpoint = "https://southeastasia.api.cognitive.microsoft.com/sts/v1.0/issueToken";
    static String serviceEndpoint = "https://southeastasia.tts.speech.microsoft.com/cognitiveservices/v1";

    public static String GetToken(){

        Map<String, String> headers = new HashMap<>();

        headers.put("Ocp-Apim-Subscription-Key",key);
        headers.put("Content-Type","application/x-www-form-urlencoded");

        try(CloseableHttpClient client = HttpClients.createDefault()){
            HttpPost post = new HttpPost(new URI(tokenEndpoint));
            for (String key : headers.keySet()) {
                post.setHeader(key, headers.get(key));
            }
            post.setEntity(new StringEntity(""));
            CloseableHttpResponse result = client.execute(post);
            return EntityUtils.toString(result.getEntity());
        } catch (URISyntaxException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return "";
    }

    public static byte[] GetAudio(String token) {
        String content = "<speak version='1.0' xml:lang='en-US'><voice xml:lang='en-US' xml:gender='Female' name='en-US-JessaRUS'>Microsoft Speech Service Text-to-Speech API</voice></speak>";
        Map<String, String> headers = new HashMap<>();
        headers.put("Authorization","Bearer " + token);
        headers.put("Content-Type","application/ssml+xml");
        headers.put("X-Microsoft-OutputFormat"," audio-16khz-64kbitrate-mono-mp3");

        try(CloseableHttpClient client = HttpClients.createDefault()){
            HttpPost post = new HttpPost(new URI(serviceEndpoint));
            for (String key : headers.keySet()) {
                post.setHeader(key, headers.get(key));
            }
            post.setEntity(new StringEntity(content));
            CloseableHttpResponse result = client.execute(post);
            byte[] bytes = EntityUtils.toByteArray(result.getEntity());
            return bytes;
        } catch (URISyntaxException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return new byte[0];
    }

    public static void main(String[] args) {
        byte[] bytes = GetAudio(GetToken());
        System.out.println(bytes.length);
        try(InputStream is = new ByteArrayInputStream(bytes)){
            Player player=new Player(is);
            player.play();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (JavaLayerException e) {
            e.printStackTrace();
        }
    }
}

Для JMF с mp3Plugin я сохраняю аудиоданные во временный файл, затем воспроизводю его.

    public static void PlayWithJMF(){
        Format input1 = new AudioFormat(AudioFormat.MPEGLAYER3);
        Format input2 = new AudioFormat(AudioFormat.MPEG);
        Format output = new AudioFormat(AudioFormat.LINEAR);
        PlugInManager.addPlugIn(
                "com.sun.media.codec.audio.mp3.JavaDecoder",
                new Format[]{input1, input2},
                new Format[]{output},
                PlugInManager.CODEC
        );

        try{
            FileOutputStream fos = new FileOutputStream("tmp.mp3");
            byte[] bytes = GetAudio(GetToken());
            System.out.println(bytes.length);
            fos.write(bytes);
            fos.flush();
            fos.close();
            File file = new File("tmp.mp3");
            javax.media.Player player = Manager.createPlayer(new MediaLocator(file.toURI().toURL()));
            player.start();
            while(true){
                if(player.getState() == 500){
                    player.close();
                    break;
                }
                Thread.sleep(500);
            }
        }catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (NoPlayerException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
...