¿Doblajes de IA sobre subs? Traducción y doblaje de videos con IA

Además de cocinar para mí y dar vueltas por la casa, los dibujos animados japoneses (o “anime”, como lo llaman los niños) son algo que aprendí a amar durante la cuarentena.

Sin embargo, el problema de ver anime es que, aparte de aprender japonés, te vuelves dependiente de traductores humanos y actores de voz para trasladar el contenido a tu idioma. A veces obtienes los subtítulos (“subs”) pero no las voces (“doblajes”). Otras veces, temporadas completas de programas no se traducen en absoluto, y te dejan al borde de tu asiento con solo resúmenes de Wikipedia y foros web de los 90 para transportarte a través de la oscuridad.

¿Entonces, que se supone que debes hacer? Obviamente, la respuesta no es pedirle a una computadora que transcriba, traduzca y actúe con voz episodios completos de un programa de televisión del japonés al inglés. La traducción es un arte cuidadoso que no se puede automatizar y requiere el toque amoroso de una mano humana. Además, incluso si usaras el aprendizaje automático para traducir un video, no podrías usar una computadora para doblar… Quiero decir, ¿quién querría escuchar las voces de las máquinas durante toda una temporada? Sería horrible. Solo un verdadero psicópata querría eso.

Entonces, en esta publicación, le mostraré cómo usar el aprendizaje automático para transcribir, traducir y doblar videos de un idioma a otro, es decir, “Doblajes de video con tecnología de IA”. Es posible que no obtenga resultados con la calidad de Netflix, pero puede usarlo para localizar conversaciones en línea y videos de YouTube en un abrir y cerrar de ojos. Comenzaremos transcribiendo audio a texto usando Google Cloud’s API de voz a texto. A continuación, traduciremos ese texto con el Traducir API. Finalmente, “doblaremos” las traducciones usando el API de texto a vozque produce voces que son, según los documentos, “humanas”.

(Por cierto, antes de que me critiques en los comentarios, debo decirte que YouTube automáticamente y gratis transcribir y traducir sus videos para usted. Entonces puede tratar este proyecto como su nuevo pasatiempo de hornear masa madre desde cero: un uso realmente ineficiente de 30 horas).

Vídeos doblados por IA: ¿suelen sonar bien?

Antes de embarcarse en este viaje, probablemente quiera saber lo que tiene que esperar. ¿Qué calidad podemos esperar lograr de manera realista de una canalización de doblaje de video ML?

Aquí hay un ejemplo doblado automáticamente de inglés a español (los subtítulos también se generan automáticamente en inglés). No he hecho ningún ajuste o ajuste en él:

Como puede ver, las transcripciones son decentes pero no perfectas, y lo mismo ocurre con las traducciones. (Ignore el hecho de que el orador a veces habla demasiado rápido, más sobre eso más adelante). En general, puede obtener fácilmente la esencia de lo que está sucediendo en este video doblado, pero no se acerca exactamente a la calidad humana.

Lo que hace que este proyecto sea más complicado (léase: más divertido) que la mayoría es que hay al menos tres posibles puntos de falla:

  1. La API Speech-to-Text puede transcribir incorrectamente el video de audio a texto
  2. La API de traducción puede traducir ese texto de forma incorrecta o incómoda.
  3. Esas traducciones pueden ser mal pronunciadas por la API de Text-to-Speech

En mi experiencia, los videos doblados más exitosos fueron aquellos que presentaban un solo orador en un flujo de audio claro y que estaban doblados del inglés a otro idioma. Esto se debe en gran parte a que la calidad de la transcripción (de voz a texto) fue mucho mayor en inglés que en otros idiomas de origen.

El doblaje de idiomas distintos al inglés resultó sustancialmente más desafiante. Aquí hay un doblaje particularmente poco impresionante del japonés al inglés de uno de mis programas favoritos, Death Note:

Si quieres dejar la traducción/doblaje a los humanos, bueno, no puedo culparte. Pero si no, ¡sigue leyendo!

Creación de un doblador de traducción de IA

Como siempre, puedes encontrar todo el código de este proyecto en el Creación con el repositorio Github de Machine Learning. Para ejecutar el código usted mismo, siga el LÉAME para configurar sus credenciales y habilitar las API. Aquí, en esta publicación, solo explicaré mis hallazgos a un alto nivel.

Primero, estos son los pasos que seguiremos:

  1. Extraer audio de archivos de video
  2. Convierte audio a texto usando la API Speech-to-Text
  3. Divida el texto transcrito en oraciones/segmentos para traducir
  4. Traducir texto
  5. Genere versiones de audio habladas del texto traducido
  6. Acelera el audio generado para alinearlo con el orador original en el video
  7. Coser el nuevo audio en la parte superior del pliegue de audio/video

Admito que cuando me dispuse a crear este doblador, estaba lleno de arrogancia: todo lo que tenía que hacer era conectar algunas API juntas, ¿qué podría ser más fácil? Pero como programador, toda arrogancia debe ser castigada, y chico, fui castigado.

Los bits desafiantes son los que puse en negrita arriba, que provienen principalmente de tener que alinear las traducciones con el video. Pero más sobre esto en un momento.

Uso de la API de voz a texto de Google Cloud

El primer paso para traducir un video es transcribir su audio a palabras. Para hacer esto, utilicé la API Speech-to-Text de Google Cloud. Esta herramienta puede reconocer audio hablado en 125 idiomas, pero como mencioné anteriormente, la calidad es más alta en inglés. Para nuestro caso de uso, querremos habilitar un par de características especiales, como:

  • Modelos mejorados. Estos son modelos de Speech-to-Text que han sido entrenados en tipos de datos específicos (“video”, “phone_call”) y generalmente son de mayor calidad. Usaremos el modelo de “video”, por supuesto.
  • Filtros de blasfemias. Esta bandera evita que la API devuelva palabras malsonantes.
  • Compensaciones de tiempo de palabra. Esta bandera le dice a la API que queremos que se devuelvan las palabras transcritas junto con las veces que el hablante las dijo. Usaremos estas marcas de tiempo para ayudar a alinear nuestros subtítulos y doblajes con el video de origen.
  • Adaptación del habla. Por lo general, Speech-to-Text tiene más problemas con palabras o frases poco comunes. Si sabe que es probable que aparezcan ciertas palabras o frases en su video (es decir, “descenso de gradiente”, “máquina de vectores de soporte”), puede pasarlas a la API en una matriz que hará que sea más probable que se transcriban:
client = speech.SpeechClient()  
# Audio must be uploaded to a GCS bucket if it's > 5 min
audio = speech.RecognitionAudio(uri="gs://path/to/my/audio.wav")
    
config = speech.RecognitionConfig(
  language_code="en-US"
  # Automatically transcribe punctuation 
  enable_automatic_punctuation=True,
  enable_word_time_offsets=True,
  speech_contexts=[
    # Boost the likelihood of recognizing these words:
    
  ],
  profanity_filter=True,
  use_enhanced="video",
  model="video")

res = client.long_running_recognize(config=config, audio=audio).result()

La API devuelve el texto transcrito junto con las marcas de tiempo a nivel de palabra como JSON. Como ejemplo, transcribí este video. Puede ver el JSON devuelto por la API en esta esencia. El resultado también nos permite hacer una verificación rápida de la calidad:

Lo que en realidad dije:

“Desarrolladores de software. No somos conocidos por nuestro estilo rockero, ¿verdad? O son ¿nosotros? Hoy, les mostraré cómo usé ML para estar más a la moda, inspirándome en personas influyentes”.

Lo que la API pensó que dije:

“Desarrolladores de software. No somos conocidos por nuestro Rock y estilo. ¿Somos o somos hoy? Te mostraré cómo uso ml para crear nuevas tendencias inspirándome en personas influyentes”.

En mi experiencia, se trata de la calidad que puede esperar al transcribir audio en inglés de alta calidad. Tenga en cuenta que la puntuación está un poco fuera de lugar. Si está satisfecho con que los espectadores obtengan la esencia de un video, esto probablemente sea lo suficientemente bueno, aunque es fácil corregir manualmente las transcripciones usted mismo si habla el idioma de origen.

En este punto, podemos usar la salida de la API para generar subtítulos (no traducidos). De hecho, si ejecuta mi script con el indicador `–srt`, hará exactamente eso por usted (srt es un tipo de archivo para subtítulos):

python dubber.py my_movie_file.mp4 "en" outputDirectory --srt --targetLangs ["es"]

Máquina traductora

Ahora que tenemos las transcripciones del video, podemos usar la API de traducción para… eh… traducirlas.

Aquí es donde las cosas empiezan a ponerse un poco 🤪.

Nuestro objetivo es este: queremos poder traducir palabras en el video original y luego reproducirlas aproximadamente en el mismo momento, de modo que mi voz “doblada” hable alineada con mi voz real.

Sin embargo, el problema es que las traducciones no son palabra por palabra. Una oración traducida del inglés al japonés puede tener desordenado el orden de las palabras. Puede contener menos palabras, más palabras, palabras diferentes o (como es el caso de los modismos) una redacción completamente diferente.

Una forma de evitar esto es traduciendo todo oraciones y luego tratar de alinear los límites de tiempo de esas oraciones. Pero incluso esto se vuelve complicado, porque ¿cómo denotas una sola oración? En inglés, podemos dividir palabras por signos de puntuación, es decir:

"Hi! My name is Dale. What's up?" --> ["Hi", "My name is Dale", "What's up"]

Pero la puntuación difiere según el idioma (no hay ¿ en inglés), y algunos idiomas no separan las oraciones con ningún signo de puntuación.

Además, en el habla de la vida real, a menudo no hablamos en oraciones completas. ¿Sabes?

Otro inconveniente que dificulta la traducción de las transcripciones es que, en general, el más contexto que introduce en un modelo de traducción, la traducción de mayor calidad que puede esperar. Entonces, por ejemplo, si traduzco la siguiente oración al francés:

“Me siento azul, pero también me gusta el rosa”.

Voy a buscar la traducción:

“Je me sens bleu, mais j’aime aussi le rose”.

Esto es exacto. Pero si divido esa oración en dos (“Me siento triste” y “Pero también me gusta el rosa”) y traduzco cada parte por separado, obtengo:

“Je me sens triste, mais j’aime aussi le rose”, es decir, “Me siento triste, pero también me gusta el rosa”.

Todo esto es para decir que cuanto más cortemos el texto antes de enviarlo a la API de traducción, peor será la calidad de las traducciones (aunque será más fácil alinearlas temporalmente con el video).

En última instancia, la estrategia que elegí fue dividir las palabras habladas cada vez que el orador hacía una pausa de más de un segundo al hablar. Aquí hay un ejemplo de cómo se veía:

   ,
    ,
    ,

Naturalmente, esto condujo a algunas traducciones incómodas (es decir, “o somos nosotros” es un fragmento extraño de traducir), pero descubrí que funcionó bastante bien. Aquí está donde se ve esa lógica en el código.

Barra lateral: también noté que la precisión de las marcas de tiempo devueltas por la API Speech-to-Text era significativamente menor para los idiomas distintos del inglés, lo que disminuyó aún más la calidad del doblaje de inglés a inglés.

Y una última cosa. Si ya sabe cómo quiere que se traduzcan ciertas palabras (es decir, mi nombre, “Dale”, siempre debe traducirse simplemente como “Dale”), puede mejorar la calidad de la traducción aprovechando la función “glosario” de la API de traducción. Avanzado. Escribí una publicación de blog sobre eso aquí.

La API de traducción de medios

Da la casualidad de que Google Cloud está trabajando en una nueva API para manejar exactamente el problema de traducir palabras habladas. se llama el API de traducción de medios, y ejecuta la traducción en audio directamente (es decir, sin intermediario de texto transcrito). No pude usar esa API en este proyecto porque aún no devuelve marcas de tiempo (la herramienta se encuentra actualmente en versión beta), pero creo que sería genial usarla en futuras iteraciones.

Texto a voz

Ahora, la parte divertida: ¡elegir voces de computadora! Si lees acerca de mi convertidor de PDF a audiolibro, sabes que me encanta tener una voz de computadora con un sonido divertido. Para generar audio para el doblaje, utilicé la API de Google Cloud Text-to-Speech. La API TTS puede generar muchas voces diferentes en diferentes idiomas con diferentes acentos, que puedes encontrar y jugar aquí. Las voces “estándar” pueden sonar un poco, er, cascado, si sabes a lo que me refiero, pero el WaveNet las voces, que son generadas por redes neuronales de alta calidad, suenan decentemente humanas.

Aquí me encontré con otro problema que no preveí: ¿qué pasa si la voz de una computadora habla mucho más lento que el altavoz original de un video, por lo que el archivo de audio generado es demasiado largo? Entonces sería imposible alinear los doblajes con el video fuente. O, ¿qué pasa si una traducción es más detallada que la redacción original, lo que genera el mismo problema?

Para lidiar con este problema, jugué con el speakingRate parámetro disponible en la API de Text-to-Speech. Esto le permite acelerar o ralentizar la voz de una computadora:

    # Instantiates a client
    client = texttospeech.TextToSpeechClient()

    # Set the text input to be synthesized
    synthesis_input = texttospeech.SynthesisInput(text="Hello World")

    voice = texttospeech.VoiceSelectionParams(
        language_code=languageCode, name=voiceName
    )

    # Select the type of audio file you want returned
    audio_config = texttospeech.AudioConfig(
        audio_encoding=texttospeech.AudioEncoding.MP3,
        # Speed up or slow down speaking
        speaking_rate=speakingRate 
    )

    # Perform the text-to-speech request on the text input with the selected
    # voice parameters and audio file type
    response = client.synthesize_speech(
        input=synthesis_input,
        voice=voice,
        audio_config=audio_config
    )

Entonces, si tomó la computadora más extenso para hablar una oración que lo hizo para el orador original del video, aumenté la velocidad de habla hasta que la computadora y el humano tomaron aproximadamente la misma cantidad de tiempo.

¿Suena un poco complicado? Así es como se ve el código:

def speakUnderDuration(text, languageCode, durationSecs, voiceName=None):
    """Speak text within a certain time limit.
    If audio already fits within duratinSecs, no changes will be made.

    Args:
        text (String): Text to be spoken
        languageCode (String): language code, i.e. "en"
        durationSecs (int): Time limit in seconds
        voiceName (String, optional): See https://cloud.google.com/text-to-speech/docs/voices

    Returns:
        bytes : Audio in wav format
    """
    # First, generate audio with speakingRate = 1
    baseAudio = speak(text, languageCode, voiceName=voiceName)
 
    # Save audio to a temporary file
    f = tempfile.NamedTemporaryFile(mode="w+b")
    f.write(baseAudio)
    f.flush()
 
    # Get the sample's duration
    baseDuration = AudioSegment.from_mp3(f.name).duration_seconds
    f.close()

    # How fast was the generated audio compared to the original?
    ratio = baseDuration / durationSecs

    # if the audio fits, return it
    if ratio <= 1:
        return baseAudio

    # If the base audio is too long to fit in the segment, increase
    # the speaking rate
    ratio = round(ratio, 1)
    # speakingRate must be <= 4
    if ratio > 4:
        ratio = 4
    return speak(text, languageCode, voiceName=voiceName, speakingRate=ratio)

Esto resolvió el problema de alinear el audio con el video, pero a veces significaba que los parlantes de la computadora en mis copias eran un poco torpemente rápidos. Pero eso es un problema para V2.

¿Valió la pena?

¿Conoces la expresión “Juega juegos estúpidos, gana premios estúpidos”? Parece que cada proyecto de ML que construyo aquí es algo así como un trabajo de amor, pero esta vez, me encanta mi premio estúpido: la capacidad de generar una cantidad ilimitada de doblajes de anime raros, robóticos e incómodos, que a veces son un poco decentes.

Mira mis resultados aquí:

Fuente del artículo

Deja un comentario