2 votes

La combinaison de deux sorties TTS dans un seul fichier mp3 ne fonctionne pas

Je souhaite combiner deux requêtes à l'API de synthèse vocale de Google cloud en une seule sortie mp3. La raison pour laquelle je dois combiner deux requêtes est que la sortie doit contenir deux langues différentes.

Le code ci-dessous fonctionne bien pour de nombreuses combinaisons de paires de langues, mais malheureusement pas pour toutes. Si je demande par exemple une phrase en anglais et une en allemand et que je les combine, tout fonctionne. Si je demande une phrase en anglais et une en japonais, je ne peux pas combiner les deux fichiers en une seule sortie. La sortie ne contient que la première phrase et au lieu de la deuxième phrase, il y a un silence.

J'ai essayé plusieurs fois de combiner les deux sorties, mais le résultat reste le même. Le code ci-dessous devrait montrer le problème.

Veuillez d'abord exécuter le code avec : python synthesize_bug.py --t1 'Hallo' --code1 de-De --t2 'August' --code2 de-De Cela fonctionne parfaitement.

python synthesize_bug.py --t1 'Hallo' --code1 de-De --t2 '' --code2 ja-JP Cela ne fonctionne pas. Les fichiers individuels sont corrects, mais les fichiers combinés contiennent du silence au lieu de la partie japonaise. De même, si l'on utilise deux phrases japonaises, tout fonctionne.

J'ai déjà déposé un rapport de bogue auprès de Google, sans réponse pour l'instant, mais il se peut que je sois le seul à faire quelque chose d'erroné avec les hypothèses d'encodage. J'espère que quelqu'un aura une idée.

#!/usr/bin/env python

import argparse

# [START tts_synthesize_text_file]
def synthesize_text_file(text1, text2, code1, code2):
    """Synthesizes speech from the input file of text."""
    from apiclient.discovery import build
    import base64

    service = build('texttospeech', 'v1beta1')
    collection = service.text()

    data1 = {}
    data1['input'] = {}
    data1['input']['ssml'] = '<speak><break time="2s"/></speak>'
    data1['voice'] = {}
    data1['voice']['ssmlGender'] = 'FEMALE'
    data1['voice']['languageCode'] = code1
    data1['audioConfig'] = {}
    data1['audioConfig']['speakingRate'] = 0.8
    data1['audioConfig']['audioEncoding'] = 'MP3'

    request = collection.synthesize(body=data1)
    response = request.execute() 
    audio_pause = base64.b64decode(response['audioContent'].decode('UTF-8'))
    raw_pause = response['audioContent']

    ssmlLine = '<speak>' + text1 + '</speak>' 

    data1 = {}
    data1['input'] = {}
    data1['input']['ssml'] = ssmlLine
    data1['voice'] = {}
    data1['voice']['ssmlGender'] = 'FEMALE'
    data1['voice']['languageCode'] = code1
    data1['audioConfig'] = {}
    data1['audioConfig']['speakingRate'] = 0.8
    data1['audioConfig']['audioEncoding'] = 'MP3'

    request = collection.synthesize(body=data1)
    response = request.execute() 

    # The response's audio_content is binary.
    with open('output1.mp3', 'wb') as out:
        out.write(base64.b64decode(response['audioContent'].decode('UTF-8')))
        print('Audio content written to file "output1.mp3"')

        audio_text1 = base64.b64decode(response['audioContent'].decode('UTF-8'))
        raw_text1 = response['audioContent']

    ssmlLine = '<speak>' + text2 + '</speak>' 

    data2 = {}
    data2['input'] = {}
    data2['input']['ssml'] = ssmlLine
    data2['voice'] = {}
    data2['voice']['ssmlGender'] = 'MALE'
    data2['voice']['languageCode'] = code2 #'ko-KR'
    data2['audioConfig'] = {}
    data2['audioConfig']['speakingRate'] = 0.8
    data2['audioConfig']['audioEncoding'] = 'MP3'

    request = collection.synthesize(body=data2)
    response = request.execute() 

    # The response's audio_content is binary.
    with open('output2.mp3', 'wb') as out:
        out.write(base64.b64decode(response['audioContent'].decode('UTF-8')))
        print('Audio content written to file "output2.mp3"')

    audio_text2 = base64.b64decode(response['audioContent'].decode('UTF-8'))
    raw_text2 = response['audioContent']

    result = audio_text1 + audio_pause + audio_text2
    with open('result.mp3', 'wb') as out:
        out.write(result)
    print('Audio content written to file "result.mp3"')

    raw_result = raw_text1 + raw_pause + raw_text2
    with open('raw_result.mp3', 'wb') as out:
        out.write(base64.b64decode(raw_result.decode('UTF-8')))
    print('Audio content written to file "raw_result.mp3"')
# [END tts_synthesize_text_file]ls

if __name__ == '__main__':
    parser = argparse.ArgumentParser(
        description=__doc__,
        formatter_class=argparse.RawDescriptionHelpFormatter)
    parser.add_argument('--t1')
    parser.add_argument('--code1')
    parser.add_argument('--t2')
    parser.add_argument('--code2')
    args = parser.parse_args()

    synthesize_text_file(args.t1, args.t2, args.code1, args.code2)

1voto

Pyotr Points 31

Vous trouverez la réponse ici : https://issuetracker.google.com/issues/120687867

Réponse courte : La raison pour laquelle cela ne fonctionne pas n'est pas claire, mais Google propose une solution de contournement consistant à écrire les fichiers au format .wav, à les combiner, puis à réencoder le résultat au format mp3.

0voto

Arron Stowne Points 73

J'ai réussi à faire cela en NodeJS avec une seule fonction (je ne sais pas si c'est optimal, mais au moins ça marche). Peut-être pourriez-vous vous en inspirer J'ai utilisé la dépendance memory-streams de npm

var streams = require('memory-streams');
function mergeAudios(audios) {
  var reader = new streams.ReadableStream();
  var writer = new streams.WritableStream();
  audios.forEach(element => {
    if (element instanceof streams.ReadableStream) {
      element.pipe(writer)
    }
    else {
      writer.write(element)
    }
  });
  reader.append(writer.toBuffer())
  return reader
}

Le paramètre d'entrée est une liste qui contient ReadableStream ou responce.audioContent de l'opération synthesizeSpeech. S'il s'agit d'un flux lisible, il utilise l'opération pipe, s'il s'agit d'un contenu audio, il utilise la méthode write. A la fin, tout le contenu est passé dans un readabblestream.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X